<?php

namespace helper\payment\sumpay;

use helper\Client;

class AopClient
{
    public string $gatewayUrl = "https://entrance.sumpay.cn/gateway.htm";

    public string $appId;

    public string $privateKey;

    public string $publicKey;

    public string $password;

    public string $version = '1.0';

    public string $format = 'JSON';

    public string $charset = 'UTF-8';

    public string $domain = '';

    public string $timestamp;

    public string $terminalType = 'wap';

    public string $signType = 'CERT';

    public string $sign = '';

    public function execute($request): array
    {
        // 签名规则
        // 公共参数
        $config = [
            'version' => $this->version,
            'format' => $this->format,
            'app_id' => $this->appId,
            'timestamp' => $this->timestamp ?? date('YmdHis'),
            'terminal_type' => $this->terminalType,
            'sign_type' => $this->signType,
            'sign' => $this->sign,
        ];
        $bizContent = array_merge($config, $request->getBizContent());//所有请求参数

        //1.参数的排放顺序按照首字母ASCII码进行升序排列。
        ksort($bizContent);
        //2.除文档中明确标注不参与签名的参数外（sign、sign_type不参与签名），所有值不为空的参数均需参与签名。
        unset($bizContent['sign_type']);
        unset($bizContent['sign']);
        $bizContent = array_filter($bizContent);// 空字符不参与签名
        // 3.将已有json数组中的参数按照key_1=value_1&key_2=value2的形式进行排列
        $sign = http_build_query($bizContent);
        $privateKeyPath = app()->getRootPath() . $this->privateKey;
        $bizContent['sign'] = $this->sign($sign, $privateKeyPath, $this->password);
        $bizContent['sign_type'] = 'CERT';

        // 发送请求
        $client = new Client();
        $response = $client->request('POST', $this->gatewayUrl, [
            'headers' => ['Content-Type' => 'application/x-www-form-urlencoded'],
            'form_params' => $bizContent,
        ]);
        return [
            'code' => $response->getStatusCode(),
            'data' => $response->getBody()
        ];
    }

    /**
     * 签名
     * @param string $data 签名数据(需要先排序，然后拼接)
     * @param string $privateKeyPath 私钥证书路径
     * @param string $password 证书密码
     * @return string 签名
     */
    function sign(string $data, string $privateKeyPath, string $password)
    {
        $certs = array();
        openssl_pkcs12_read(file_get_contents($privateKeyPath), $certs, $password);
        if (!$certs) {
            return '';
        }
        $signature = '';
        //调用openssl内置签名方法，生成签名
        openssl_sign($data, $signature, $certs['pkey'], 'sha256');
        return base64_encode($signature);
    }
}